﻿using Basic.HrDAL;
using Basic.HrModel.DB;
using Basic.HrModel.Power;
using Basic.HrRemoteModel;
using Basic.HrRemoteModel.Power.Model;
using WeDonekRpc.Client;
using WeDonekRpc.Helper;
using WeDonekRpc.Model;

namespace Basic.HrCollect.Impl
{
    internal class PowerCollect : IPowerCollect
    {
        private readonly IPowerDAL _Power;

        public PowerCollect ( IPowerDAL power )
        {
            this._Power = power;
        }
        public T[] Gets<T> ( PowerQuery query ) where T : class, new()
        {
            return this._Power.Gets<T>(query);
        }
        public Result[] Query<Result> ( PowerQuery query, IBasicPage paging, out int count ) where Result : class, new()
        {
            return this._Power.Query<Result>(query, paging, out count);
        }

        public PowerRouteDto[] GetEnables ( long[] ids )
        {
            if ( ids.IsNull() )
            {
                return this._Power.Gets<PowerRouteDto>(a => a.IsEnable).OrderBy(a => a.Sort).ToArray();
            }
            else
            {
                PowerRouteDto[] list = this._Power.Gets<PowerRouteDto>(a => ids.Contains(a.Id) && a.IsEnable);
                List<long> prtId = new List<long>();
                list.ForEach(c =>
                {
                    if ( c.LevelCode != string.Empty )
                    {
                        c.LevelCode.SplitWriteLong('|', prtId);
                    }
                });
                long[] pids = prtId.Distinct().ToArray();
                PowerRouteDto[] menus = this._Power.Gets<PowerRouteDto>(a => pids.Contains(a.Id) && a.PowerType == PowerType.dir);
                return list.Add(menus).OrderBy(a => a.Sort).ToArray();
            }
        }
        public PowerBasic[] Gets ( long[] ids )
        {
            return this._Power.Gets<PowerBasic>(ids);
        }

        public PowerDto[] GetDtos ( long[] subSystemId, PowerGetParam param )
        {
            return this._Power.Gets<PowerDto>(subSystemId, param).OrderBy(a => a.Sort).ToArray();
        }
        public long[] Filters ( long[] ids, PowerType powerType )
        {
            return this._Power.Gets(a => ids.Contains(a.Id) && a.PowerType == powerType, a => a.Id);
        }
        public PowerDto[] GetDtos ( long subSystemId, PowerGetParam param )
        {
            return this._Power.Gets<PowerDto>(subSystemId, param).OrderBy(a => a.Sort).ToArray();
        }
        public bool Set ( DBPowerList sour, PowerSet set )
        {
            if ( sour.IsEnable )
            {
                throw new ErrorException("hr.power.not.can.update");
            }
            else if ( ( set.Name != sour.Name || set.ParentId != sour.ParentId ) && this._Power.IsExists(c => c.SubSystemId == set.SubSystemId
            && c.ParentId == set.ParentId
            && c.Name == set.Name) )
            {
                throw new ErrorException("hr.power.name.repeat");
            }
            if ( set.ParentId == sour.ParentId )
            {
                PowerSetData data = set.ConvertMap<PowerSet, PowerSetData>();
                return this._Power.Update(sour, set);
            }
            PowerSetBase dto = set.ConvertMap<PowerSet, PowerSetBase>();
            string prtLevel;
            int num = 0;
            if ( set.ParentId != 0 )
            {
                var prt = this._Power.Get(set.ParentId, c => new
                {
                    c.SubSystemId,
                    c.LevelCode,
                    c.LevelNum
                });
                dto.SubSystemId = prt.SubSystemId;
                dto.LevelCode = ( prt.LevelCode.IsNull() ? "|" : prt.LevelCode ) + set.ParentId + "|";
                dto.LevelNum = prt.LevelNum + 1;
                prtLevel = dto.LevelCode + sour.Id + "|";
                num = sour.LevelNum - prt.LevelNum;
            }
            else
            {
                dto.LevelNum = 1;
                dto.LevelCode = string.Empty;
                prtLevel = "|";
                num = sour.LevelNum - 1;
            }
            dto.Sort = this._Power.GetSort(sour.SubSystemId, set.ParentId) + 1;
            if ( sour.PowerType == PowerType.menu )
            {
                return this._Power.Update(sour, dto);
            }
            string old = ( sour.LevelCode.IsNull() ? "|" : sour.LevelCode ) + sour.Id + "|";
            var children = this._Power.Gets(c => c.SubSystemId == sour.SubSystemId && c.LevelCode.StartsWith(old), c => new
            {
                c.Id,
                c.LevelCode,
                c.LevelNum
            });
            int len = old.Length;
            this._Power.Set(sour, dto, children.ConvertAll(a => new PowerLevelSet
            {
                Id = a.Id,
                LevelCode = prtLevel + a.LevelCode.Remove(0, len),
                LevelNum = a.LevelNum - num
            }));
            return true;
        }

        public long Add ( PowerSet add )
        {
            return this.Add(add, null, null);
        }
        public long Add ( PowerSet add, string linkType, long? linkPk )
        {
            if ( this._Power.IsExists(c => c.SubSystemId == add.SubSystemId
            && c.ParentId == add.ParentId
            && c.Name == add.Name) )
            {
                throw new ErrorException("hr.power.name.repeat");
            }
            DBPowerList db = add.ConvertMap<PowerSet, DBPowerList>();
            db.Sort = this._Power.GetSort(add.SubSystemId, add.ParentId) + 1;
            db.LinkType = linkType;
            db.LinkPk = linkPk;
            if ( add.ParentId != 0 )
            {
                var prt = this._Power.Get(add.ParentId, a => new
                {
                    a.LevelCode,
                    a.LevelNum
                });
                if ( prt.LevelNum == 1 )
                {
                    db.LevelCode = "|" + add.ParentId + "|";
                }
                else
                {
                    db.LevelCode = prt.LevelCode + add.ParentId + "|";
                }
                db.LevelNum = prt.LevelNum + 1;
            }
            else
            {
                db.LevelNum = 1;
            }
            this._Power.Add(db);
            return db.Id;
        }
        public DBPowerList Get ( long id )
        {
            return this._Power.Get(id);
        }

        public bool SetSort ( DBPowerList db, int sort )
        {
            if ( db.Sort == sort )
            {
                return false;
            }
            this._Power.SetSort(db, sort);
            return true;
        }

        public void Delete ( DBPowerList db )
        {
            if ( db.IsEnable )
            {
                throw new ErrorException("hr.power.not.can.delete");
            }
            this._Power.Delete(db.Id);
        }

        public bool SetIsEnable ( DBPowerList db, bool isEnable )
        {
            if ( db.IsEnable == isEnable )
            {
                return false;
            }
            this._Power.SetIsEnable(db.Id, isEnable);
            return true;
        }

        public Result Find<Result> ( string linkType, long linkPk ) where Result : class, new()
        {
            return this._Power.Get<Result>(a => a.LinkType == linkType && a.LinkPk == linkPk);
        }
    }
}
